package billing.logger;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;


public class Logger {
	static Map<String,Logger> loggerMap = new HashMap<String, Logger>();
	private String name;
	static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
	static String logPattern = "%DATE %NAME [%LEVEL] %MSG ";
	static Level baseLevel = Level.INFO;
	static boolean isPrintStackTrace = false;
	
	
	private Logger(String name) {
		this.name = name;
	}
	
	public static Logger getLogger(Class<?> clazz) {
		String key = clazz.getName();
		Logger value = loggerMap.get(key);
		if(null == value){
			value = new Logger(key);
			loggerMap.put(key, value);
		}
		return value;
	}
	
	public static Logger getLogger(String className) {
		String key = className;
		Logger value = loggerMap.get(key);
		if(null == value){
			value = new Logger(key);
			loggerMap.put(key, value);
		}
		return value;
	}

	public void debug(Object message) {
		debug(message, null);
	}
	
	public void info(Object message) {
		info(message, null);
	}
	
	public void warn(Object message) {
		warn(message, null);
	}
	
	public void error(Object message) {
		error(message, null);
	}
	public void error(Exception e) {
		error(e.getMessage(), e);
	}
	
	public void fatal(Object message) {
		fatal(message, null);
	}
	
	public void trace(Object message) {
		trace(message, null);
	}
	

	public void debug(Object message, Throwable e) {
		printLogger(Level.DEBUG, message, e);
	}

	public void info(Object message, Throwable e) {
		printLogger(Level.INFO, message, e);
	}

	public void warn(Object message, Throwable e) {
		printLogger(Level.WARN, message, e);
	}
	
	public void error(Object message, Throwable e) {
		printLogger(Level.ERROR, message, e);
	}

	public void fatal(Object message, Throwable e) {
		printLogger(Level.FATAL, message, e);
	}
	
	public void trace(Object message, Throwable e) {
		printLogger(Level.TRACE, message, e);
	}
	
	private void printLogger(Level level,Object message,Throwable e){
		if(level.getLevelValue() >= baseLevel.getLevelValue()){
			String msg = messageFormat(level, message);
			if(Level.ERROR == level){
				System.err.println(msg);
			}else{
				System.out.println(msg);
			}
			if(isPrintStackTrace && null !=e && e instanceof Exception){
				e.printStackTrace();
			}
		}
	}
	
	private String messageFormat(Level level,Object message){
		String result = logPattern;
		result = result.replaceAll("%DATE", dateFormat.format(new java.util.Date()));
		result = result.replaceAll("%NAME", name);
		result = result.replaceAll("%LEVEL", level.getUpperCase());
		result = result.replaceAll("%level", level.getLowerCase());
		String msg = "" + message;
		result = result.replace("%MSG", msg);
		return result;
	}

	public String getName() {
		return this.name;
	}

	public boolean isTraceEnabled() {
		return true;
	}

	public boolean isDebugEnabled() {
		return Level.DEBUG.getLevelValue() >= baseLevel.getLevelValue();
	}

	public void log(String fqcn, Level level, Object message, Throwable e) {
		printLogger(level, message, e);
	}

	public boolean isInfoEnabled() {
		return Level.INFO.getLevelValue() >= baseLevel.getLevelValue();
	}

	public boolean isEnabledFor(Level level) {
		return level.getLevelValue() >= baseLevel.getLevelValue();
	}
}
